<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GPU Kernel Codegen Quiz</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            color: white;
        }

        .quiz-container {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
        }

        .question {
            background: rgba(255, 255, 255, 0.05);
            border-radius: 15px;
            padding: 25px;
            margin: 20px 0;
            border-left: 4px solid #4CAF50;
            display: none;
        }

        .question.active {
            display: block;
            animation: slideIn 0.3s ease-in-out;
        }

        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateY(20px);
            }

            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .question h3 {
            color: #4CAF50;
            margin-bottom: 15px;
            font-size: 1.2em;
        }

        .options {
            margin: 15px 0;
        }

        .option {
            background: rgba(255, 255, 255, 0.1);
            border: none;
            border-radius: 10px;
            padding: 12px 15px;
            margin: 8px 0;
            width: 100%;
            text-align: left;
            color: white;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 14px;
        }

        .option:hover {
            background: rgba(255, 255, 255, 0.2);
            transform: translateX(5px);
        }

        .option.selected {
            background: rgba(76, 175, 80, 0.3);
            border: 2px solid #4CAF50;
        }

        .option.correct {
            background: rgba(76, 175, 80, 0.5);
            border: 2px solid #4CAF50;
        }

        .option.incorrect {
            background: rgba(244, 67, 54, 0.5);
            border: 2px solid #f44336;
        }

        .controls {
            text-align: center;
            margin-top: 25px;
        }

        .btn {
            background: linear-gradient(45deg, #4CAF50, #45a049);
            border: none;
            border-radius: 25px;
            color: white;
            padding: 12px 25px;
            margin: 0 10px;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }

        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
        }

        .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
        }

        .progress {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 10px;
            height: 8px;
            margin: 20px 0;
            overflow: hidden;
        }

        .progress-bar {
            background: linear-gradient(90deg, #4CAF50, #45a049);
            height: 100%;
            transition: width 0.3s ease;
            border-radius: 10px;
        }

        .score {
            text-align: center;
            font-size: 18px;
            margin: 20px 0;
            font-weight: bold;
        }

        .explanation {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 10px;
            padding: 15px;
            margin-top: 15px;
            border-left: 4px solid #2196F3;
            display: none;
        }

        .explanation.show {
            display: block;
            animation: fadeIn 0.3s ease-in-out;
        }

        @keyframes fadeIn {
            from {
                opacity: 0;
            }

            to {
                opacity: 1;
            }
        }

        .code {
            background: rgba(0, 0, 0, 0.3);
            padding: 10px;
            border-radius: 5px;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            margin: 10px 0;
            overflow-x: auto;
        }

        h1 {
            text-align: center;
            color: #4CAF50;
            margin-bottom: 30px;
            font-size: 2.5em;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        }

        .final-score {
            text-align: center;
            font-size: 24px;
            margin: 30px 0;
            display: none;
        }

        .final-score.show {
            display: block;
            animation: bounceIn 0.5s ease-in-out;
        }

        @keyframes bounceIn {
            0% {
                transform: scale(0.3);
                opacity: 0;
            }

            50% {
                transform: scale(1.05);
            }

            70% {
                transform: scale(0.9);
            }

            100% {
                transform: scale(1);
                opacity: 1;
            }
        }
    </style>
</head>

<body>
    <div class="quiz-container">
        <h1>🚀 GPU Kernel Codegen Quiz</h1>

        <div class="progress">
            <div class="progress-bar" id="progressBar"></div>
        </div>

        <div class="score">
            Question <span id="currentQ">1</span> of <span id="totalQ">10</span> | Score: <span
                id="score">0</span>/<span id="totalScore">10</span>
        </div>

        <!-- Questions -->
        <div class="question active" data-question="1">
            <h3>1. What are the two main GPU architectures supported by this codegen?</h3>
            <div class="options">
                <button class="option" data-answer="a">CUDA and OpenCL</button>
                <button class="option" data-answer="b">CUDA and Metal</button>
                <button class="option" data-answer="c">Metal and Vulkan</button>
                <button class="option" data-answer="d">CUDA and DirectX</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: CUDA and Metal</strong><br>
                The code explicitly handles two GPU architectures through the <code>GPUArch</code> enum:
                <code>GPUArch::CUDA</code> and <code>GPUArch::Metal</code>. You can see this in the kernel generation
                where different syntax is used for each architecture.
            </div>
        </div>

        <div class="question" data-question="2">
            <h3>2. What is the purpose of the `split_kernels` function?</h3>
            <div class="options">
                <button class="option" data-answer="a">To optimize memory usage</button>
                <button class="option" data-answer="b">To break the computation graph into separate GPU kernels</button>
                <button class="option" data-answer="c">To validate the graph structure</button>
                <button class="option" data-answer="d">To generate kernel code</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: To break the computation graph into separate GPU kernels</strong><br>
                The <code>split_kernels</code> function takes a computation graph and splits it into multiple kernel
                graphs, handling dependencies between kernels. This is necessary because GPU kernels have limitations on
                synchronization and memory access patterns.
            </div>
        </div>

        <div class="question" data-question="3">
            <h3>3. What does the `var_to_char` function do?</h3>
            <div class="options">
                <button class="option" data-answer="a">Converts variables to ASCII characters</button>
                <button class="option" data-answer="b">Generates unique variable names using letters</button>
                <button class="option" data-answer="c">Validates variable names</button>
                <button class="option" data-answer="d">Converts characters to variables</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: Generates unique variable names using letters</strong><br>
                The function converts integer variable IDs to letter-based names (a, b, c, ..., z, aa, ab, etc.). It
                uses base-26 encoding to create readable variable names in the generated kernel code.
            </div>
        </div>

        <div class="question" data-question="4">
            <h3>4. What is the maximum number of loop levels before switching to explicit for-loops?</h3>
            <div class="options">
                <button class="option" data-answer="a">3</button>
                <button class="option" data-answer="b">5</button>
                <button class="option" data-answer="c">6</button>
                <button class="option" data-answer="d">8</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: 6</strong><br>
                The code uses GPU thread dimensions (blockIdx.x/y/z and threadIdx.x/y/z) for the first 6 loop levels,
                then switches to explicit for-loops for deeper nesting. This is evident in the condition
                <code>if *loop_level < 6</code>.
            </div>
        </div>

        <div class="question" data-question="5">
            <h3>5. What does `GraphTerm::NewAcc` represent?</h3>
            <div class="options">
                <button class="option" data-answer="a">A new memory allocation</button>
                <button class="option" data-answer="b">A new accumulator variable for reductions</button>
                <button class="option" data-answer="c">A new GPU thread</button>
                <button class="option" data-answer="d">A new kernel launch</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: A new accumulator variable for reductions</strong><br>
                <code>NewAcc</code> creates an accumulator array with a starting value, used for reduction operations.
                The code calculates the size needed and initializes the accumulator with the starting value.
            </div>
        </div>

        <div class="question" data-question="6">
            <h3>6. What is the difference between `SMEMLoad` and `SMEMRead`?</h3>
            <div class="options">
                <button class="option" data-answer="a">SMEMLoad writes to shared memory, SMEMRead reads from it</button>
                <button class="option" data-answer="b">SMEMLoad loads from global memory to shared memory, SMEMRead
                    reads from shared memory</button>
                <button class="option" data-answer="c">They are the same operation</button>
                <button class="option" data-answer="d">SMEMLoad is for CUDA, SMEMRead is for Metal</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: SMEMLoad loads from global memory to shared memory, SMEMRead reads from shared
                    memory</strong><br>
                <code>SMEMLoad</code> copies data from global memory to shared memory with a sync barrier, while
                <code>SMEMRead</code> just reads from the shared memory location that was previously loaded.
            </div>
        </div>

        <div class="question" data-question="7">
            <h3>7. How are kernel dependencies handled in the meta-graph?</h3>
            <div class="options">
                <button class="option" data-answer="a">Through shared memory</button>
                <button class="option" data-answer="b">Through global memory buffers and topological sorting</button>
                <button class="option" data-answer="c">Through GPU streams</button>
                <button class="option" data-answer="d">Through atomic operations</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: Through global memory buffers and topological sorting</strong><br>
                The code creates a meta-graph of kernel dependencies, using <code>GMEMBuffer::PrevKernel</code> to track
                outputs from previous kernels as inputs to subsequent kernels. Topological sorting ensures correct
                execution order.
            </div>
        </div>

        <div class="question" data-question="8">
            <h3>8. What does the `stride` parameter in `LoopIn`/`LoopOut` control?</h3>
            <div class="options">
                <button class="option" data-answer="a">Loop increment step</button>
                <button class="option" data-answer="b">Memory offset for each loop iteration</button>
                <button class="option" data-answer="c">Number of threads per block</button>
                <button class="option" data-answer="d">Kernel execution order</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: Memory offset for each loop iteration</strong><br>
                The stride determines how much to offset pointer addresses for each loop iteration. Special stride
                values like accumulator strides (checked with <code>stride.is_acc()</code>) handle reduction operations
                differently.
            </div>
        </div>

        <div class="question" data-question="9">
            <h3>9. What triggers the creation of a new kernel in `split_kernels`?</h3>
            <div class="options">
                <button class="option" data-answer="a">Memory allocation exceeding limits</button>
                <button class="option" data-answer="b">Loop dependencies between grid/block level operations</button>
                <button class="option" data-answer="c">Too many operations in one kernel</button>
                <button class="option" data-answer="d">Shared memory overflow</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: Loop dependencies between grid/block level operations</strong><br>
                A new kernel is created when there's a dependency between <code>LoopOut</code> and <code>LoopIn</code>
                operations at the grid/block level (less than 3 levels deep), as these require synchronization across
                the entire GPU.
            </div>
        </div>

        <div class="question" data-question="10">
            <h3>10. What is the purpose of the `toposort_subset` function?</h3>
            <div class="options">
                <button class="option" data-answer="a">To sort kernels by execution time</button>
                <button class="option" data-answer="b">To topologically sort only a subset of graph nodes</button>
                <button class="option" data-answer="c">To optimize memory layout</button>
                <button class="option" data-answer="d">To validate graph connectivity</button>
            </div>
            <div class="explanation">
                <strong>Correct Answer: To topologically sort only a subset of graph nodes</strong><br>
                This function performs topological sorting on a specified subset of nodes from the graph, maintaining
                dependency order while only considering the nodes in the given subset. This is used when processing
                individual kernel subgraphs.
            </div>
        </div>

        <div class="controls">
            <button class="btn" id="prevBtn" onclick="previousQuestion()" disabled>Previous</button>
            <button class="btn" id="nextBtn" onclick="nextQuestion()" disabled>Next</button>
            <button class="btn" id="submitBtn" onclick="submitAnswer()" disabled>Submit Answer</button>
            <button class="btn" id="restartBtn" onclick="restartQuiz()" style="display: none;">Restart Quiz</button>
        </div>

        <div class="final-score" id="finalScore">
            <h2>🎉 Quiz Complete!</h2>
            <p>Your final score: <span id="finalScoreValue">0</span>/10</p>
            <p id="scoreMessage"></p>
        </div>
    </div>

    <script>
        let currentQuestion = 1;
        let totalQuestions = 10;
        let score = 0;
        let selectedAnswer = null;
        let answered = false;

        const correctAnswers = {
            1: 'b', 2: 'b', 3: 'b', 4: 'c', 5: 'b',
            6: 'b', 7: 'b', 8: 'b', 9: 'b', 10: 'b'
        };

        function updateProgress() {
            const progress = (currentQuestion - 1) / totalQuestions * 100;
            document.getElementById('progressBar').style.width = progress + '%';
            document.getElementById('currentQ').textContent = currentQuestion;
            document.getElementById('totalQ').textContent = totalQuestions;
            document.getElementById('score').textContent = score;
            document.getElementById('totalScore').textContent = totalQuestions;
        }

        function selectOption(option) {
            if (answered) return;

            document.querySelectorAll('.question.active .option').forEach(opt => {
                opt.classList.remove('selected');
            });

            option.classList.add('selected');
            selectedAnswer = option.dataset.answer;
            document.getElementById('submitBtn').disabled = false;
        }

        function submitAnswer() {
            if (answered) return;

            answered = true;
            const correctAnswer = correctAnswers[currentQuestion];
            const isCorrect = selectedAnswer === correctAnswer;

            if (isCorrect) {
                score++;
                document.getElementById('score').textContent = score;
            }

            document.querySelectorAll('.question.active .option').forEach(opt => {
                if (opt.dataset.answer === correctAnswer) {
                    opt.classList.add('correct');
                } else if (opt.dataset.answer === selectedAnswer && !isCorrect) {
                    opt.classList.add('incorrect');
                }
            });

            document.querySelector('.question.active .explanation').classList.add('show');
            document.getElementById('submitBtn').disabled = true;

            if (currentQuestion < totalQuestions) {
                document.getElementById('nextBtn').disabled = false;
            } else {
                showFinalScore();
            }
        }

        function nextQuestion() {
            if (currentQuestion < totalQuestions) {
                document.querySelector('.question.active').classList.remove('active');
                currentQuestion++;
                document.querySelector(`[data-question="${currentQuestion}"]`).classList.add('active');
                resetQuestion();
                updateProgress();
            }
        }

        function previousQuestion() {
            if (currentQuestion > 1) {
                document.querySelector('.question.active').classList.remove('active');
                currentQuestion--;
                document.querySelector(`[data-question="${currentQuestion}"]`).classList.add('active');
                resetQuestion();
                updateProgress();
            }
        }

        function resetQuestion() {
            answered = false;
            selectedAnswer = null;
            document.getElementById('submitBtn').disabled = true;
            document.getElementById('nextBtn').disabled = true;
            document.getElementById('prevBtn').disabled = currentQuestion === 1;

            document.querySelectorAll('.question.active .option').forEach(opt => {
                opt.classList.remove('selected', 'correct', 'incorrect');
            });

            document.querySelector('.question.active .explanation').classList.remove('show');
        }

        function showFinalScore() {
            document.getElementById('finalScoreValue').textContent = score;
            const percentage = (score / totalQuestions) * 100;
            let message = '';

            if (percentage >= 90) {
                message = '🌟 Excellent! You have a deep understanding of GPU kernel codegen!';
            } else if (percentage >= 70) {
                message = '👍 Great job! You understand most of the key concepts.';
            } else if (percentage >= 50) {
                message = '📚 Good effort! Review the explanations to strengthen your understanding.';
            } else {
                message = '💪 Keep studying! This is complex material - practice makes perfect.';
            }

            document.getElementById('scoreMessage').textContent = message;
            document.getElementById('finalScore').classList.add('show');
            document.getElementById('restartBtn').style.display = 'inline-block';
        }

        function restartQuiz() {
            currentQuestion = 1;
            score = 0;
            selectedAnswer = null;
            answered = false;

            document.querySelectorAll('.question').forEach(q => q.classList.remove('active'));
            document.querySelector('[data-question="1"]').classList.add('active');
            document.getElementById('finalScore').classList.remove('show');
            document.getElementById('restartBtn').style.display = 'none';

            resetQuestion();
            updateProgress();
        }

        // Event listeners
        document.querySelectorAll('.option').forEach(option => {
            option.addEventListener('click', () => selectOption(option));
        });

        // Initialize
        updateProgress();
        document.getElementById('prevBtn').disabled = true;
    </script>
</body>

</html>